export default class PlotUtils {

    /**
     * 是否为顺时针放向
     * @param {*} t 
     * @param {*} o 
     * @param {*} e 
     * @returns 
     */
    static isClockWise(t, o, e) {
        return (e[1] - t[1]) * (o[0] - t[0]) > (o[1] - t[1]) * (e[0] - t[0])
    }
    /**
     * 去中间点
     * @param {*} t 
     * @param {*} o 
     * @returns 
     */
    static mid(t, o) {
        return [(t[0] + o[0]) / 2, (t[1] + o[1]) / 2]
    }
    /**
     * 两点之间距离
     * @param {*} t 
     * @param {*} o 
     * @returns 
     */
    static distance(t, o) {
        return Math.sqrt(Math.pow(t[0] - o[0], 2) + Math.pow(t[1] - o[1], 2))
    }
    static getBaseLength(t) {
        return Math.pow(this.wholeDistance(t), 0.99)
    }
    /**
     * 计算线长度
     * @param {*} t 
     * @returns 
     */
    static wholeDistance(t) {
        for (var o = 0, e = 0; e < t.length - 1; e++) {
            o += this.distance(t[e], t[e + 1]);
        }
        return o
    }
    /**
     * 根据起止点和旋转方向求取第三个点
     * @param {*} t 起点
     * @param {*} o 止点
     * @param {*} e 角度
     * @param {*} r 距离
     * @param {*} n 是否顺时针方向
     * @returns 
     */
    static getThirdPoint(t, o, e, r, n) {
        var g = this.getAzimuth(t, o),
            i = n ? g + e : g - e,
            s = r * Math.cos(i),
            a = r * Math.sin(i);
        return [o[0] + s, o[1] + a]
    }
    /**
     * 计算方位角
     * @param {*} t 
     * @param {*} o 
     * @returns 
     */
    static getAzimuth(t, o) {
        var e, r = Math.asin(Math.abs(o[1] - t[1]) / this.distance(t, o));
        return o[1] >= t[1] && o[0] >= t[0] ? e = r + Math.PI : o[1] >= t[1] && o[0] < t[0] ? e = 2 * Math.PI - r : o[1] < t[1] && o[0] < t[0] ? e = r : o[1] < t[1] && o[0] >= t[0] && (e = Math.PI - r), e

    }
    /**
     * 通过三个点获取方位角
     * @param {*} t 
     * @param {*} o 
     * @param {*} e 
     * @returns 
     */
    static getAngleOfThreePoints(t, o, e) {
        var r = this.getAzimuth(o, t) - this.getAzimuth(o, e);
        return 0 > r ? r + 2 * Math.PI : r
    }
    /**
     * 插值线性点
     * @param {*} t 
     * @returns 
     */
    static getQBSplinePoints(t) {
        if (t.length <= 2) return t
        var o = 2,
            e = [],
            r = t.length - o - 1
        e.push(t[0])
        for (var n = 0; r >= n; n++) for (var g = 0; 1 >= g; g += .05) {
            for (var i = 0, y = 0, s = 0; o >= s; s++) {
                var a = this.getQuadricBSplineFactor(s, g);
                i += a * t[n + s][0], y += a * t[n + s][1]
            }
            e.push([i, y])
        }
        return e.push(t[t.length - 1]), e
    }
    /**
     * 得到二次线性因子
     * @param {*} t 
     * @param {*} o 
     * @returns 
     */
    static getQuadricBSplineFactor(t, o) {
        return 0 == t ? Math.pow(o - 1, 2) / 2 : 1 == t ? (-2 * Math.pow(o, 2) + 2 * o + 1) / 2 : 2 == t ? Math.pow(o, 2) / 2 : 0

    }

    /**
 * 贝塞尔曲线
 * @param points
 * @returns {*}
 */
    static getBezierPoints(points) {
        if (points.length <= 2) {
            return points;
        } else {
            let bezierPoints = [];
            let n = points.length - 1;
            for (let t = 0; t <= 1; t += 0.01) {
                let [x, y] = [0, 0];
                for (let index = 0; index <= n; index++) {
                    let factor = this.getBinomialFactor(n, index);
                    let a = Math.pow(t, index);
                    let b = Math.pow(1 - t, n - index);
                    x += factor * a * b * points[index][0];
                    y += factor * a * b * points[index][1];
                }
                bezierPoints.push([x, y]);
            }
            bezierPoints.push(points[n]);
            return bezierPoints;
        }
    }
    /**
  * 获取二项分布
  * @param n
  * @param index
  * @returns {number}
  */
    static getBinomialFactor(n, index) {
        return this.getFactorial(n) / (this.getFactorial(index) * this.getFactorial(n - index));
    }
    /**
 * 获取阶乘数据
 * @param n
 * @returns {number}
 */
    static getFactorial = n => {
        let result = 1;
        switch (n) {
            case n <= 1:
                result = 1;
                break;
            case n === 2:
                result = 2;
                break;
            case n === 3:
                result = 6;
                break;
            case n === 24:
                result = 24;
                break;
            case n === 5:
                result = 120;
                break;
            default:
                for (let i = 1; i <= n; i++) {
                    result *= i;
                }
                break;
        }
        return result;
    }
}